/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.workflow.service.usertask.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.mvc.BaseMethodArgument;
import com.je.common.base.service.MetaBusService;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.PlatformService;
import com.je.common.base.service.rpc.BeanService;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.ibatis.extension.plugins.pagination.Page;
import com.je.servicecomb.JECloud;
import com.je.servicecomb.RpcSchemaFactory;
import com.je.workflow.service.usertask.MonitorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.util.*;

import static com.je.servicecomb.JECloud.PRODUCT_CORE_RBAC;
import static com.je.workflow.service.usertask.vo.UserTaskVo.JudgmentDay;

@Service
public class MonitorServiceImpl implements MonitorService {

    private static final String[] END_STATUS = new String[]{"END", "INVALID"};

    @Autowired
    private MetaService metaService;
    @Autowired
    private PlatformService platformService;

    @Override
    public Page load(BaseMethodArgument param, HttpServletRequest request) {
        if (param.getLimit() == 0) {
            param.setLimit(-1);
        }
        Page page = new Page(param.getPage(), param.getLimit());
        String funcCode = param.getFuncCode();
        //内容和功能名称是经过转义的，这里重新jquery
        if (!Strings.isNullOrEmpty(param.getjQuery())) {
            buildQuery(param);
        }
        ConditionsWrapper wrapper = platformService.buildWrapper(param, request);
        List<Map<String, Object>> list = this.metaService.load(funcCode, page, wrapper);
        for (Map<String, Object> map : list) {
            if (!Arrays.asList(END_STATUS).contains(map.get("STATE"))) {
                map.put("SY_CREATETIME", "");
                String piId = String.valueOf(map.get("EXECUTION_PIID"));
                List<DynaBean> userNameList = metaService.select("JE_WORKFLOW_RN_TASK", ConditionsWrapper.builder().eq("TASK_PIID", piId), "ASSIGNEE_NAME");
                Set<String> PENDING_PERSON = new HashSet<>();
                for (DynaBean user : userNameList) {
                    PENDING_PERSON.add(user.getStr("ASSIGNEE_NAME"));
                }
                map.put("PENDING_PERSON", String.join(",", PENDING_PERSON));
            } else {
                map.put("EXECUTION_NODE_NAME", "结束节点");
            }
            if (map.get("EXECUTION_CONTENT") == null || map.get("EXECUTION_CONTENT").toString().length() == 0) {
                map.put("EXECUTION_CONTENT", buildTitle(String.valueOf(map.get("EXECUTION_TITLE")), String.valueOf(map.get("EXECUTION_START_TIME"))));
            }
        }
        page.setRecords(list);
        return page;
    }

    private void buildQuery(BaseMethodArgument param) {
        JSONObject jqueryJ = JSONObject.parseObject(param.getjQuery());
        JSONArray jsonArray = JSONArray.parse(String.valueOf(jqueryJ.get("custom")));
        if (jsonArray.size() > 0) {
            JSONObject jsonObject = JSONObject.parseObject(jsonArray.get(0).toString());
            String paramValue = JSONObject.parseObject(JSONArray.parse(jsonObject.get("value").toString()).get(0).toString()).get("value").toString();
            jsonObject.put("type", "and");
            jsonObject.put("cn", "and");
            String[] codeArray = new String[]{"PROCESS_NAME", "FUNC_NAME", "EXECUTION_CONTENT", "EXECUTION_TITLE"};
            JSONArray valueArray = new JSONArray();
            for (String code : codeArray) {
                JSONObject value = new JSONObject();
                value.put("code", code);
                value.put("value", paramValue);
                value.put("type", "like");
                value.put("cn", "or");
                valueArray.add(value);
            }
            jsonObject.put("value", valueArray);
            jqueryJ.put("custom", jsonObject);
            param.setjQuery(jqueryJ.toJSONString());
        }
    }

    @Override
    @Transactional
    public void clearDirtyData() {
        //EXECUTION_PRODUCT_CODE=产品code BUSINESS_KEY=主键
//        new Thread(() -> {
        String monitorSql = "SELECT EXECUTION_PRODUCT_CODE,BUSINESS_KEY,TABLE_CODE,STATE FROM JE_WORKFLOW_MONITOR";
        List<Map<String, Object>> monitorData = metaService.selectSql(monitorSql);
        for (Map<String, Object> map : monitorData) {
            String productCode = (String) map.get("EXECUTION_PRODUCT_CODE");
            String businessKey = (String) map.get("BUSINESS_KEY");
            String tableCode = (String) map.get("TABLE_CODE");
            String state = (String) map.get("STATE");
            int removeB = executeRemoteQuery(productCode, tableCode, businessKey);
            if (removeB == 1) {
                deleteExecution(state, businessKey);
            }
        }
//        }).start();
    }

    private void deleteExecution(String state, String businessKey) {
        if (Arrays.asList(END_STATUS).contains(state)) {
            List<DynaBean> executions = metaService.select("JE_WORKFLOW_HI_EXECUTION",
                    ConditionsWrapper.builder().eq("BUSINESS_KEY", businessKey));
            for (DynaBean dynaBean : executions) {
                dynaBean.setStr(BeanService.KEY_TABLE_CODE, "JE_WORKFLOW_HI_EXECUTION_RECYCLE_BIN");
                metaService.insert(dynaBean);
                List<DynaBean> tasks = metaService.select("JE_WORKFLOW_HI_TASK",
                        ConditionsWrapper.builder().eq("JE_WORKFLOW_HI_EXECUTION_ID", dynaBean.getPkValue()));
                for (DynaBean task : tasks) {
                    task.setStr(BeanService.KEY_TABLE_CODE, "JE_WORKFLOW_HI_TASK_RECYCLE_BIN");
                    metaService.insert(task);
                }
                metaService.executeSql("DELETE FROM JE_WORKFLOW_HI_TASK WHERE JE_WORKFLOW_HI_EXECUTION_ID={0}", dynaBean.getPkValue());
            }
            metaService.executeSql("DELETE FROM JE_WORKFLOW_HI_EXECUTION WHERE BUSINESS_KEY={0}", businessKey);
        } else {
            List<DynaBean> executions = metaService.select("JE_WORKFLOW_RN_EXECUTION",
                    ConditionsWrapper.builder().eq("BUSINESS_KEY", businessKey));
            for (DynaBean dynaBean : executions) {
                dynaBean.setStr(BeanService.KEY_TABLE_CODE, "JE_WORKFLOW_RN_EXECUTION_RECYCLE_BIN");
                metaService.insert(dynaBean);
                List<DynaBean> tasks = metaService.select("JE_WORKFLOW_RN_TASK",
                        ConditionsWrapper.builder().eq("JE_WORKFLOW_RN_EXECUTION_ID", dynaBean.getPkValue()));
                for (DynaBean task : tasks) {
                    task.setStr(BeanService.KEY_TABLE_CODE, "JE_WORKFLOW_RN_TASK_RECYCLE_BIN");
                    metaService.insert(task);
                }
                metaService.executeSql("DELETE FROM JE_WORKFLOW_RN_TASK WHERE JE_WORKFLOW_RN_EXECUTION_ID={0}", dynaBean.getPkValue());
            }
            metaService.executeSql("DELETE FROM JE_WORKFLOW_RN_EXECUTION WHERE BUSINESS_KEY={0}", businessKey);
        }
    }

    protected int executeRemoteQuery(String product, String tableCode, String pkValue) {
        if (JECloud.PRODUCT_CORE_WORKFLOW.equals(product) || JECloud.PRODUCT_CORE_META.equals(product) || PRODUCT_CORE_RBAC.equals(product)) {
            return 0;
        }
        try {
            MetaBusService metaBusService = RpcSchemaFactory.getRemoteProvierClazz(product, "metaBusService", MetaBusService.class);
            if (metaBusService.selectDataExistsByPkValue(tableCode, pkValue)) {
                return 0;
            }
        } catch (Exception e) {
            return 0;
        }
        return 1;
    }


    private static String buildTitle(String title, String startTime) {
        try {
            String day = JudgmentDay(startTime);
            if (day == null) {
                day = startTime.substring(0, 10);
            }
            try{
                title = String.format(title, "（" + day + "）");
            }catch (Exception e){
                e.printStackTrace();
            }
            return title;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return title;
    }

}
